package com.xxg.renrensearch.service;

import com.xxg.renrencommon.domain.bean.CarryProductInfo;
import com.xxg.renrencommon.domain.bean.ProductGatherInfo;
import com.xxg.renrensearch.cache.StatisticsCache;
import com.xxg.renrensearch.dao.CarryProductInfoDao;
import com.xxg.renrensearch.dao.CarryProductSettingInfoDao;
import com.xxg.renrensearch.dao.ProductGatherInfoDao;
import com.xxg.renrensearch.domain.fieldenum.CarryAuthEnum;
import com.xxg.renrensearch.domain.result.CarryCountResult;
import com.xxg.renrensearch.domain.result.ShopCarryTypeCount;
import com.xxg.renrensearch.domain.result.ShopGatherCount;
import com.xxg.renrensearch.es.RenRenShopEs;
import com.xxg.renrensearch.repository.RenrenShopShopRepository;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 统计相关接口实现
 *
 * @author xuxiaogang
 * @date 2021-12-03
 */
@Service
public class StatisticsServiceImpl implements StatisticsService {
    private final RenRenShopEs renRenShopEs;
    private final RenrenShopShopRepository renrenShopShopRepository;
    private final CarryProductSettingInfoDao carryProductSettingInfoDao;
    private final StatisticsCache statisticsCache;
    private final ProductGatherInfoDao productGatherInfoDao;
    private final CarryProductInfoDao carryProductInfoDao;

    public StatisticsServiceImpl(RenRenShopEs renRenShopEs, RenrenShopShopRepository renrenShopShopRepository,
                                 CarryProductSettingInfoDao carryProductSettingInfoDao, StatisticsCache statisticsCache,
                                 ProductGatherInfoDao productGatherInfoDao, CarryProductInfoDao carryProductInfoDao) {
        this.renRenShopEs = renRenShopEs;
        this.renrenShopShopRepository = renrenShopShopRepository;
        this.carryProductSettingInfoDao = carryProductSettingInfoDao;
        this.statisticsCache = statisticsCache;
        this.productGatherInfoDao = productGatherInfoDao;
        this.carryProductInfoDao = carryProductInfoDao;
    }

    @Override
    public Map<Integer, Integer> getShopSpuCount() {
        Map<Integer, Integer> data = statisticsCache.getShopSpuCountCache();
        if (data == null) {
            data = renRenShopEs.getShopSpuCount();
            statisticsCache.writeShopSpuCountCache(data);
        }
        return data;
    }

    @Override
    public Map<Integer, ShopCarryTypeCount[]> getShopCarryTypeSpuCount() {
        Map<Integer, ShopCarryTypeCount[]> map = statisticsCache.getCarryTypeCount();
        if (map == null) {
            List<ShopCarryTypeCount> infoList = carryProductSettingInfoDao.findAllCarryInfo();
            int shopCount = (int) renrenShopShopRepository.count();
            map = new HashMap<>(shopCount * 4 / 3 + 1);
            for (ShopCarryTypeCount info : infoList) {
                Integer shopId = info.getShopId();
                if (!map.containsKey(shopId)) {
                    // 第一个元素放全局设置，第二个结果放允许数量，第三个结果放不允许数量
                    map.put(shopId, new ShopCarryTypeCount[3]);
                }
                if (info.getType() == 0) {
                    // 全局设置
                    map.get(shopId)[0] = info;
                } else {
                    // 个别设置
                    if (info.getCarryAble()) {
                        map.get(shopId)[1] = info;
                    } else {
                        map.get(shopId)[2] = info;
                    }
                }
            }
            statisticsCache.writeCarryTypeCountCache(map);
        }
        return map;
    }

    @Override
    public List<Integer> getShopCarryTypeSpuCountById(Integer shopId, Integer carryAuth) {
        // 返回结果集合，第一个元素表示的逻辑关系，当为1时则表示包含，为-1时表示排除
        List<Integer> list = new LinkedList<>();
        List<ShopCarryTypeCount> infoList = carryProductSettingInfoDao.findCarryInfoById(shopId);
        ShopCarryTypeCount[] counts = new ShopCarryTypeCount[4];
        for (ShopCarryTypeCount info : infoList) {
            if (info.getType() == 0) {
                // 全局设置,最多一个
                counts[0] = info;
            } else {
                // 个别设置，两类情况
                // 一类允许带货
                if (info.getCarryAble()) {
                    if (info.getCarryApplyAble()) {
                        // 需要申请
                        counts[1] = info;
                    } else {
                        // 无需申请
                        counts[2] = info;
                    }
                } else {
                    // 二类不允许带货
                    counts[3] = info;
                }
            }
        }
        if (CarryAuthEnum.NOT_ALLOWED.getValue().equals(carryAuth)) {
            // 不允许带货的spuId列表
            // 首先判断全局设置
            if (counts[0] == null || counts[0].getCarryAble()) {
                // 全局设置默认为都可带货，则返回不允许带货的个人设置
                list.add(1);
                if (counts[3] != null) {
                    list.addAll(counts[3].getSpuIds());
                }
            } else {
                // 全局设置都不可带货，则排除掉允许带货的spuId列表即可
                list.add(-1);
                if (counts[1] != null) {
                    list.addAll(counts[1].getSpuIds());
                }
                if (counts[2] != null) {
                    list.addAll(counts[2].getSpuIds());
                }
            }
        } else if (CarryAuthEnum.REQUIRED.getValue().equals(carryAuth)) {
            // 需要申请的spuId列表
            if (counts[0] != null && counts[0].getCarryAble() && counts[0].getCarryApplyAble()) {
                // 全局需要申请，则排除掉需要无需申请和不允许带货的spuId列表
                list.add(-1);
                if (counts[2] != null) {
                    list.addAll(counts[2].getSpuIds());
                }
                if (counts[3] != null) {
                    list.addAll(counts[3].getSpuIds());
                }
            } else {
                // 全局默认都可带货无需申请|全局不可带货｜全局无需申请，则返回需要申请的个人设置
                list.add(1);
                if (counts[1] != null) {
                    list.addAll(counts[1].getSpuIds());
                }
            }
        } else {
            // 无需申请的spuId列表
            if (counts[0] == null || (counts[0].getCarryAble() && !counts[0].getCarryApplyAble())) {
                // 全局默认｜全局可带货无需申请,排除掉需要申请和不支持带货的个人设置
                list.add(-1);
                if (counts[1] != null) {
                    list.addAll(counts[1].getSpuIds());
                }
                if (counts[3] != null) {
                    list.addAll(counts[3].getSpuIds());
                }
            } else {
                // 全局需要申请｜全局不可带货，则返回无需申请的个人设置
                list.add(1);
                if (counts[2] != null) {
                    list.addAll(counts[2].getSpuIds());
                }
            }
        }
        return list;
    }

    @Override
    public List<Integer> getCarriedSpuIdByShopIdAndOriShopId(Integer myShopId, Integer oriShopId) {
        List<CarryProductInfo> infos = carryProductInfoDao.getSpuIdsByShopIdAndOriShopId(myShopId, oriShopId);
        List<Integer> list = new LinkedList<>();
        infos.forEach(e -> list.add(e.getSpuId()));
        return list;
    }

    @Override
    public Map<Integer, Map<Integer, Integer>> getShopGatherCount() {
        Map<Integer, Map<Integer, Integer>> result = statisticsCache.getGatherCount();
        if (result == null) {
            List<ShopGatherCount> infos = productGatherInfoDao.getAllGatherCount();
            int shopCount = (int) renrenShopShopRepository.count();
            result = new HashMap<>(shopCount * 4 / 3 + 1);
            for (ShopGatherCount info : infos) {
                Integer shopId = info.getShopId();
                if (!result.containsKey(shopId)) {
                    result.put(shopId, new HashMap<>(shopCount * 4 / 3 + 1));
                }
                result.get(shopId).put(info.getOriginShopId(), info.getCount());
            }
            statisticsCache.writeGatherCountCache(result);
        }
        return result;
    }

    @Override
    public Map<Integer, Map<Integer, Integer>> getShopCarriedCount() {
        Map<Integer, Map<Integer, Integer>> result = statisticsCache.getCarriedCount();
        if (result == null) {
            List<CarryCountResult> results = carryProductInfoDao.getCountByShopIdGroupByOriShopId();
            int shopCount = (int) renrenShopShopRepository.count();
            result = new HashMap<>(shopCount * 4 / 3 + 1);
            for (CarryCountResult countResult : results) {
                Integer shopId = countResult.getShopId();
                if (!result.containsKey(shopId)) {
                    result.put(shopId, new HashMap<>(shopCount * 4 / 3 + 1));
                }
                result.get(shopId).put(countResult.getOriginShopId(), countResult.getCount());
            }
            statisticsCache.writeCarriedCountCache(result);
        }
        return result;
    }

    @Override
    public List<Integer> getGatherSpuIdByShopId(Integer shopId) {
        List<ProductGatherInfo> infos = productGatherInfoDao.getGatherListByShopId(shopId);
        return infos.stream().map(ProductGatherInfo::getNewSpuId).collect(Collectors.toList());
    }

    @Override
    public Integer[] getCarriedBeCarriedCounts(Integer shopId) {
        int count1 = carryProductInfoDao.findCarriedCountByShopId(shopId);
        int count2 = carryProductInfoDao.findBeCarriedCountByShopId(shopId);
        return new Integer[]{count1, count2};
    }
}
